package com.yuxin.tongyi.lsll.util;

import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

import javax.security.auth.Subject;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserFactory;
import org.xmlpull.v1.XmlSerializer;

import android.util.Log;
import android.util.Xml;

public class XMLUtil {
	private final static String TAG = "XMLUtil";
	private ArrayList<Object> objList = null;

	public ArrayList<Object> getObjList() {
		return objList;
	}

	private Stack<Object> objStack = null;

	public Stack<Object> getObjStack() {
		return objStack;
	}

	/**
	 * 根据xml路径读取xml内容
	 * 
	 * @param xmlPath
	 */
	public String readServerXML(InputStream is) {
		try {
			objList = new ArrayList<Object>();
			objStack = new Stack<Object>();
			XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
			XmlPullParser parser = factory.newPullParser();
			parser.setInput(new InputStreamReader(is));
			int eventType = parser.getEventType();
			String result = "";

			documentWhile: while (eventType != XmlPullParser.END_DOCUMENT) {// 循环至文档结束
				String nodeName = parser.getName();// 获取节点名称
				documentSwitch: switch (eventType) {
				case XmlPullParser.START_DOCUMENT:// 文档开始
					break documentSwitch;
				case XmlPullParser.START_TAG:// 节点开始（包括ServerInfo,head,resultCode,body,StudentInfo,studentId,studentName,classId,className,gradeId)
					if ("ServerInfo".equals(nodeName)) {// 如果是serverInfo不做处理
					} else if ("head".equals(nodeName)) {// 如果是head进入鉴权处理
						headWhile: while (eventType != XmlPullParser.END_DOCUMENT) {// 进入head内循环
							eventType = parser.next();// 循环至下一个节点
							nodeName = parser.getName();// 获取节点名称
							headSwitch: switch (eventType) {
							case XmlPullParser.START_TAG:// 节点开始（包括resultCode,loginName,password)
								if ("resultCode".equals(nodeName)) {// 如果是resultCode判断是否成功，0为成功，其余直接返回result并结束xml文档循环
									result = parser.nextText();
									break headSwitch;
								}
							case XmlPullParser.END_TAG:// 节点结束（只为判断节点为head时跳出head循环）
								if ("head".equals(nodeName)) {
									break headWhile;
								}
							}
						}
					} else if ("body".equals(nodeName)) {// 如果是body进入对象封装处理
						if (!result.equals("0")) {
							result = parser.nextText();
							break documentWhile;
						}
						if (!setObject(parser, eventType, nodeName)) {
							result = "对象解析错误！";
							break documentWhile;
						}
					}

					break;
				}
				eventType = parser.next();
			}
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 根据xml路径读取xml内容
	 * 
	 * @param xmlPath
	 */
	public String readClientXML(InputStream is) {
		try {
			objList = new ArrayList<Object>();
			objStack = new Stack<Object>();
			XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
			XmlPullParser parser = factory.newPullParser();
			parser.setInput(new InputStreamReader(is));
			int eventType = parser.getEventType();
			String result = "";

			documentWhile: while (eventType != XmlPullParser.END_DOCUMENT) {// 循环至文档结束
				String nodeName = parser.getName();// 获取节点名称
				documentSwitch: switch (eventType) {
				case XmlPullParser.START_DOCUMENT:// 文档开始
					if (!setObject(parser, eventType, nodeName)) {
						result = "对象解析错误！";
						break documentWhile;
					}
					break documentSwitch;
				case XmlPullParser.START_TAG:// 节点开始
//					Log.i(TAG, "nodeName is "+nodeName);
//					if (!setObject(parser, eventType, nodeName)) {
//						result = "对象解析错误！";
//						break documentWhile;
//					}
					break documentSwitch;
				}
				eventType = parser.next();
			}
			return result;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 封装对象
	 * 
	 * @param parser
	 * @param eventType
	 * @param nodeName
	 * @return
	 */
	private boolean setObject(XmlPullParser parser, int eventType,
			String nodeName) {
		try {
			boolean isFieldOut = false;
			Class<?> pojo = null;
			bodyWhile: while (eventType != XmlPullParser.END_DOCUMENT) {// 进入body内循环
				eventType = parser.next();// 循环至下一个节点
				nodeName = parser.getName();// 获取节点名称
				String objectName = "";
				bodySwitch: switch (eventType) {
				case XmlPullParser.START_TAG:// 节点开始（包括各个对象与对象的属性)
					if (nodeName.matches("^[A-Z][a-zA-Z]*")) {
						try {
							pojo = Class.forName("com.yuxin.tongyi.lsll.pojo." + nodeName);
							Object obj = pojo.newInstance(); // 实例化
							objectName = nodeName;
							objectWhile: while ((eventType = parser
									.getEventType()) != XmlPullParser.END_DOCUMENT) { // 为对象属性赋值
								
								if (!isFieldOut) {
//									Log.i(TAG, "进入if");
									eventType = parser.next();// 循环至下一个节点
									// 获取节点名称
//									Log.i(TAG, "当前if的eventType是："+eventType);
								} else {
									isFieldOut=false;
//									Log.i(TAG, "进入else");
								}
								nodeName = parser.getName();
//								Log.i(TAG, "当前else的eventType是："+eventType);
//								Log.i(TAG, "当前的nodeName是："+nodeName);
//								Log.i(TAG, "开始执行：");
								objectSwitch: switch (eventType) {
								case XmlPullParser.START_TAG:// 节点开始（包括对象的各个属性）
									try {
										Field field = obj.getClass().getDeclaredField(nodeName);
										if (field != null) {
											// 为属性赋值
											field.setAccessible(true);
											Class<?> typeClass = field.getType();
											// 如果有一对多关联关系，获取填充关联类数据并赋值
											if (typeClass.getName().equals(
													"java.util.List")) {
												field.set(
														obj,
														setListField(parser,
																nodeName, field));
												field.setAccessible(false);
												isFieldOut = true;
											} else {
												Constructor<?> con = typeClass
														.getConstructor(typeClass);
												Object value = con
														.newInstance(parser
																.nextText());
												field.set(obj, value);
												field.setAccessible(false);
											}
										}
										break objectSwitch;
									} catch (Exception e) {
										e.printStackTrace();
										return false;
									}
								case XmlPullParser.END_TAG: // 节点结束（只为判断对象结束时跳出对象循环）
//									Log.i(TAG, "进入END_TAG");
//									Log.i(TAG, "当前END_TAG的eventType是："+eventType);
//									Log.i(TAG, "当前END_TAG的nodeName是："+nodeName);
									if (objectName.equals(nodeName)) {
										objStack.push(obj);
										objList.add(obj);
//										Log.i(TAG, "进入END_TAG");
//										Log.i(TAG, "当前END_TAG的eventType是："+eventType);
//										Log.i(TAG, "当前END_TAG的nodeName是："+nodeName);
										break objectWhile;
									}
								}
								
							}
						} catch (Exception e) {
							e.printStackTrace();
							return false;
						}

					}
					break bodySwitch;
				case XmlPullParser.END_TAG:// 节点结束（只为判断节点为head时跳出循环）
//					Log.i(TAG, "进入bodyWhile的END_TAG");
//					Log.i(TAG, "当前bodyWhile的END_TAG的eventType是："+eventType);
//					Log.i(TAG, "当前bodyWhile的END_TAG的nodeName是："+nodeName);
					if ("body".equals(nodeName)) {
						break bodyWhile;
					}
				}
			}
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	/**
	 * 封装List
	 * 
	 * @param parser
	 * @param eventType
	 * @param nodeName
	 * @return
	 */
	private ArrayList<?> setListField(XmlPullParser parser, String nodeName,
			Field field) {
		try {
			@SuppressWarnings("rawtypes")
			ArrayList subObjectList = new ArrayList();
			Object subObject = GenericsUtils.getFieldGenericType(field)
					.newInstance();
//			Log.i(TAG, "subObject is : "+subObject);
			String objectName = nodeName;
			int eventType = parser.getEventType();
			subObjectWhile: while (eventType != XmlPullParser.END_DOCUMENT) {
				eventType = parser.next();
				nodeName = parser.getName();
				subObjectSwitch: switch (eventType) {
				case XmlPullParser.START_TAG:

					try {
//						Log.i(TAG, "nodename is : "+nodeName);
						Field subField = subObject.getClass().getDeclaredField(
								nodeName);
						if (subField != null) {
							// 为属性赋值
							subField.setAccessible(true);
							Class<?> typeClass = subField.getType();
							// 如果有一对多关联关系，获取填充关联类数据并赋值
							if (typeClass.getName().equals("java.util.List")) {
								subField.set(
										subObject,
										setListField(parser, nodeName, subField));
								eventType=parser.getEventType();
								nodeName=parser.getName();
								subField.setAccessible(false);
//								Log.i(TAG, "parser's event type is : "+parser.getEventType());
								if(parser.getEventType()==XmlPullParser.END_TAG){
									
								}else{
									break subObjectSwitch;
								}
							} else {
								Constructor<?> con = typeClass
										.getConstructor(typeClass);
								Object value = con.newInstance(parser
										.nextText());
								subField.set(subObject, value);
//								Log.i(TAG, "subField is : "+subField.get(subObject));
								subField.setAccessible(false);
								break subObjectSwitch;
							}
						}
						
					} catch (Exception e) {
						e.printStackTrace();
						return null;
					}
				case XmlPullParser.END_TAG:
//					Log.i(TAG, "eventType1 is : "+eventType);
//					Log.i(TAG, "nodeName1 is : "+parser.getName());
//					Log.i(TAG, "objectName1 is : "+objectName);
					if (objectName.equals(nodeName)) {
						subObjectList.add(subObject);
						eventType = parser.next();
//						Log.i(TAG, "eventType2 is : "+eventType);
//						Log.i(TAG, "nodeName2 is : "+parser.getName());
//						Log.i(TAG, "objectName2 is : "+objectName);
						if (objectName.equals(parser.getName())) { // 如果下个节点为同一对象，重新循环赋值，否则跳出循环，返回List
							subObject = GenericsUtils.getFieldGenericType(field)
							.newInstance();
							continue subObjectWhile;
						} else {
							break subObjectWhile;
						}
					}
				}
			}
			return subObjectList;
			// }
		} catch (Exception e) {
//			Log.i(TAG, "异常");
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 将对象解析成xml
	 */
	public void parse(Writer writer, Object object) {
		try {
			XmlSerializer serializer = Xml.newSerializer();
			serializer.setOutput(writer);
			serializer.startDocument("UTF-8", true);
			serializer.startTag("", object.getClass().getSimpleName());
			Field[] fields = object.getClass().getDeclaredFields();
			for (Field field : fields) {
				// 为属性赋值
				field.setAccessible(true);
				serializer.startTag("", field.getName());
				serializer.text(field.get(object) == null ? "" : field.get(
						object).toString());
				serializer.endTag("", field.getName());
				field.setAccessible(false);
			}
			serializer.endTag("", object.getClass().getSimpleName());
			serializer.endDocument();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void parseSubObject(Writer writer, Object object) {

	}

	/**
	 * 写xml
	 */
	public void writeXML(String filePath) {
		try {
			// StudentInfo studentInfo = new StudentInfo();

			StringWriter writer = new StringWriter();
			XmlSerializer serializer = Xml.newSerializer();
			serializer.setOutput(writer);
			serializer.startDocument("UTF-8", true);
			serializer.startTag("", "ServerInfo");
			serializer.startTag("", "head");
			serializer.startTag("", "resultCode");
			serializer.text("0");
			serializer.endTag("", "resultCode");
			serializer.endTag("", "head");
			serializer.startTag("", "body");
			serializer.endTag("", "body");
			serializer.endDocument();
			// FileOutputStream fos=this.openFileOutput("user.xml",
			// MODE_PRIVATE);
			FileOutputStream fos = new FileOutputStream(filePath);
			fos.write(writer.toString().getBytes());
			fos.flush();
			fos.close();
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	/**
	 * 将xml字符流写入文件
	 * 
	 * @param fileStr
	 * @param filePath
	 * @return
	 */
	public boolean writeFile(String fileStr, String filePath) {
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(filePath);
			fos.write(fileStr.getBytes());
			fos.flush();
			return true;
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (fos != null) {
				try {
					fos.close();
				} catch (Exception e2) {
					e2.printStackTrace();
				}
			}
		}
		return false;
	}

}
